<?php
/**
 * AJAX、RSS用XML出力ヘルパー
 */
class xmloutput {
	public $xml;

	/**
	 * DOMの実体
	 */
	public $DOM;

	public $DOMchild;
	public $DOMchildIndex;

	/**
	 * 特殊DOMchild
	 */
	public $Root;
	public $Message;

	public function __construct () {
		$this->xml = array('message'=>null);
		$this->DOM = null;
		$this->DOMchildIndex = array();
		$this->DOMchild = array();
	}
	
	/**
	 * init時にoutputを変更する
	 */
	public function init () {
		//テンプレート動作は削除
		Y('Output-');
		Y('Output+', YuTori::create($this, 'putXml'));
		
		// メッセージ動作を変更
		Y('Output.Message+', YuTori::create($this, 'setMessage'));

		Y('this.initRoot+', YuTori::create($this, 'initRoot'));
		Y('this.initMessage+', YuTori::create($this, 'initMessage'));

		Y('this.addChild+', YuTori::Create($this, 'addChildDOMchild'));
		Y('this.setText+', YuTori::Create($this, 'setTextDOMchild'));

		Y('this.XML+', YuTori::create($this, 'setXml'));

		// DOMの初期化
		$this->DOM = new DomDocument();
		$this->DOM->xmlVersion = '1.0';
		$this->DOM->encoding = "UTF-8";
		$this->DOM->formatOutput = true;
	}
	
	/**
	 * Rootを初期化する
	 */
	public function initRoot ($Name = 'response') {
		$this->Root = $this->DOM->appendChild($this->DOM->createElement($Name));
		Y('Helper.List.XMLOutput.Root+', $this->Root);
		Y('Helper.List.XMLOutput.Root.Attr+', YuTori::Create($this, 'addAttrRoot'));

		Y('Helper.List.XMLOutput.Root.addChild+', YuTori::Create($this, 'addChildRoot'));
		Y('Helper.List.XMLOutput.Root.getChildIndex+', YuTori::Create($this, 'getDOMchildIndex'));
		Y('Helper.List.XMLOutput.Root.setChildText+', YuTori::Create($this, 'getDOMchildText'));
		return true;
	}

	/**
	 * Rootに属性を付与する
	 */
	public function addAttrRoot ($Name, $Value) {
		if (!$this->Root) $this->initRoot();
		$Attr = $this->Root->setAttribute($Name, $Value);
		return $Attr;
	}

	/**
	 * Rootに子ノードを追加する
	 */
	public function addChildRoot ($Name) {
		if (!$this->Root) $this->initRoot();

		$NewID = count ($this->DOMchildIndex);
		$this->DOMchildIndex[$NewID] = $Name;
		$Child = $this->Root->appendChild($this->DOM->createElement($Name));
		$this->DOMchild[$NewID] = $Child;

		Y('Logger.Debug', 'Rootに'.$NewID.'/'.$this->DOMchildIndex[$NewID].'ノード追加');

		return $Child;
	}

	/**
	 * DOMchildを検索する
	 */
	public function getDOMchildIndex ($Name, $Index = 0) {
		$IndexLoop = 0;
		foreach ((array)$this->DOMchildIndex as $key=>$val) {
			if (0 === strcasecmp ($val, $Name)) {
				if ($Index == $IndexLoop) {
					Y('Logger.Debug', 'ノード検索: '.$Name.'/'.$Index.' = '.$key);
					return $key;
				}
				$IndexLoop++;
			}
		}
		return false;
	}
	
	/**
	 * DOMchildに子ノードを追加する
	 */
	public function addChildDOMchild ($Name, $Index, $Value) {
		if (false !== ($ID = $this->getDOMchildIndex($Name, $Index))) {
			$NewID = count ($this->DOMchildIndex);
			$this->DOMchildIndex[$NewID] = $Value;
			$Child = $this->DOMchild[$ID]->appendChild($this->DOM->createElement($Value));
			$this->DOMchild[$NewID] = $Child;
			Y('Logger.Debug', 'ID:'.$ID.'に'.$NewID.'/'.$this->DOMchildIndex[$NewID].'ノード追加');
		}
		return false;
	}

	/**
	 * DOMchildにデータを挿入する
	 */
	public function setTextDOMchild ($Name, $Index, $Value) {
		if (false !== ($ID = $this->getDOMchildIndex($Name, $Index))) {
			$Child = $this->DOMchild[$ID]->appendChild($this->DOM->createTextNode($Value));
		}
		return false;
	}

	/**
	 * Messageを初期化する
	 */
	public function initMessage ($Name = 'message') {
		Y('Logger.Debug', 'メッセージ追加');
		if (!$this->Root) $this->initRoot();
		$this->Message = $this->Root->appendChild($this->DOM->createElement($Name));
		return true;
	}

	/**
	 * xmlをセットする(旧関数)※非推奨
	 */
	public function setXml ($xml) {
		Y('Logger.Debug', '非推奨のオブジェクト Helper.List.XMLOutput.XMLが呼び出されました。');
		if (!$this->Message) $this->initMessage();
		foreach ((array)$xml as $key=>$val) {
			if (is_array($val)) {
				$this->setXml ($val);
				continue;
			}
			if ($key == 'message') {
				$this->setMessage($val);
			}elseif (false !== ($ID = $this->getDOMchildIndex ($key))) {
				$this->DOMchild[$ID]->appendData($val);
			} else {
				$ID = count ($this->DOMchildIndex);
				$this->DOMchildIndex[$ID] = $key;
				$this->DOMchild[$ID] = $this->Root->appendChild($this->DOM->createElement($key));
				$this->DOMchild[$ID]->appendChild($this->DOM->createTextNode($val));
			}
		}
		return;
	}

	/**
	 * メッセージ動作
	 */
	public function setMessage ($Msg) {
		if (!$this->Message) $this->initMessage();
		$this->Message->appendChild($this->DOM->createTextNode($Msg));
		return;
	}

	/**
	 * xmlを出力する
	 */	
	public function putXml () {
		// デバッグモード時
		if (Y('Logger.Debug$')) {
			if (!$this->Root) $this->initRoot();
			$Logger = $this->Root->appendChild($this->DOM->createElement('debuglog'));
			$Log = '';
			foreach ((array)Y('Logger.getDebug') as $dLog) {
				$Log .= $dLog['trace'].':'. trim($dLog['txt']). "\n";
			}
			$Log .= '';
			$Logger->appendChild($this->DOM->createTextNode($Log));
		}

		header ('Content-type: application/xml; charset="UTF-8"');
		print $this->DOM->saveXML();

		return;
	}
}
?>